package wang.wangby.lazydoc.model;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.core.annotation.AnnotationUtils;

import lombok.Data;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import wang.wangby.annotation.Param;
import wang.wangby.annotation.Property;
import wang.wangby.annotation.Remark;
import wang.wangby.lazydoc.common.DocParameterType;
import wang.wangby.lazydoc.common.DocRules;
import wang.wangby.utils.BeanUtil;
import wang.wangby.utils.ClassUtil;
import wang.wangby.utils.StringUtil;

@Getter
@Slf4j
public class ApiParameter {
	// 参数名
	private String name;
	// 描述
	private String description;
	// 配置信息
	private Param config;
	// 上一级参数,生成input框名字的时候需要
	private ApiParameter parent;

	// 参数类型
	private DocParameterType paramType;

	// 文档生成规则
	private DocRules docRules;
	
	//在字段上配置的属性信息,可以做一些校验
	private Property property;

	/**
	 * 构造参数
	 * 
	 * @param docRules 文档生成规则
	 * @param type     参数类型
	 * @param name     参数名
	 * @param desc     参描述
	 * @param config   参数配置信息
	 * 
	 */
	public ApiParameter(DocRules docRules, DocParameterType type, String name, String desc, Param config) {
		if(StringUtil.isEmpty(desc)) {
			if(config!=null) {
				desc=config.value();
			}
		}
		
		if(StringUtil.isEmpty(desc)) {
			desc=name;
		}
		
		this.docRules = docRules;
		this.paramType = type;
		this.name = name;
		this.description = desc;
		this.config = config;
	}

	// 获取显示用类型名
	public String getTypeName() {
		return paramType.getTypeName();
	}

	public String getDescription() {
		return description;
	}

	/** 获得下级参数,当参数是复合类型的时候 */
	public List<ApiParameter> getChildren() {
		List list = new ArrayList();
		Class clazz = paramType.getRawType();
		if (paramType.isArray()) {
			clazz = paramType.getFirstGenericType();
		}

		for (Field f : docRules.getParamField(clazz)) {
			DocParameterType type = DocParameterType.getType(f.getGenericType(), paramType.getOwnerType());
			ApiParameter pa = new ApiParameter(docRules, type, f.getName(), docRules.getFieldDesc(f), this.config);
			pa.parent = this;
			pa.property=f.getAnnotation(Property.class);
			

			// 如果配置了忽略,就不显示
			if (config != null) {
				boolean ignore = false;
				for (String s : config.ignores()) {
					if (s.equals(pa.getInputName())) {
						ignore = true;
						break;
					}
				}
				if (ignore) {
					continue;
				}
			}

			list.add(pa);
		}
		return list;
	}

	public String getName() {
		return name;
	}

	// 获得输入输入框的名字
	public String getInputName() {
		if (parent == null) {
			if (docRules.hashChildren(paramType.getFirstGenericType())) {
				return "";
			}
			return name;
		}
		if (parent.getInputName().equals("")) {
			return name;
		}
		return parent.getInputName() + "." + name;
	}

	// 作为输入参数是的信息
	public List<InputParam> getDebugParams() {
		List list = new ArrayList();
		List<ApiParameter> chd = getChildren();
		if (chd.size() == 0) {
			list.add(new InputParam(this,property));
			return list;
		}
		for (ApiParameter ap : chd) {
			list.addAll(ap.getDebugParams());
		}
		return list;
	}

	public Class getType() {
		return paramType.getFirstGenericType();
	}

	//将要转为json作为输入参数
	public Object newJsonParam() {
		Object o=newInstance();
		if(paramType.isArray()) {
			List list=new ArrayList();
			list.add(o);
			return list;
		}
		return o;
	}
	
	private Object newInstance() {
		Class clazz=paramType.getFirstGenericType();
		if(ClassUtil.isPrimitive(clazz)){
			return null;
		}
		Object o=ClassUtil.newInstance(clazz);
		for(ApiParameter pa:this.getChildren()) {
			Object child=pa.newJsonParam();
			BeanUtil.set(o, pa.getName(), child);
		}
		return o;
	}

}
